import { Client } from "./Client";
import { ClientMessage } from "./ClientMessage";
import { JTimer } from "../../Ticks/JTimer";
import { getTimer } from "../../Utility/dx/getTimer";

export class AdvanceClient extends Client
{
    public static ClassName:string = "AdvanceClient";
    private monitorTimer:JTimer;
    private needMonitorIDs = {};
    private cancelMonitorIDs = {};
    public addMonitor(packetID:number,RTOTarget:any,RTOCallBack:Function,RTOPacketIDs:number[]):void
    {
        if(!RTOPacketIDs||RTOPacketIDs.length==0)return;
        if(this.needMonitorIDs["length"]==undefined)
            this.needMonitorIDs["length"]=0;
        if(this.needMonitorIDs[packetID]==undefined)
        {
            let t = getTimer();
            this.needMonitorIDs[packetID] = {time:t,target:RTOTarget,callback:RTOCallBack,ids:RTOPacketIDs};
            this.needMonitorIDs["length"]++;
        }
        for(let i = 0;i<RTOPacketIDs.length;i++)
        {
            if(this.cancelMonitorIDs[RTOPacketIDs[i]]==undefined)
            {
                this.cancelMonitorIDs[RTOPacketIDs[i]]=[packetID];
            }else
            {
                if(this.cancelMonitorIDs[RTOPacketIDs[i]].indexOf(packetID)==-1)
                    this.cancelMonitorIDs[RTOPacketIDs[i]].push(packetID);
            }
        }
        if(this.needMonitorIDs["length"]>0)
            this.startMonitor();
    }
    private startMonitor():void
    {
        if(this.monitorTimer==null)
        {
            this.monitorTimer = JTimer.GetTimer(100);
            this.monitorTimer.addTimerCallback(this,this.onMonitorTick);
        }
        !this.monitorTimer.running&&this.monitorTimer.start();
    }
    private stopMonitor():void
    {
        this.monitorTimer&&this.monitorTimer.stop();
    }
    private onMonitorTick():void
    {
        let t = getTimer();
        for(let id in this.needMonitorIDs)
        {
            let o = this.needMonitorIDs[id];
            if(o==null)continue;
            if(t-o.time>=3000)
            {
                console.log("[Client] 协议 0x"+(Number(id).toString(16))+" 未接收到数据回复！！！");
                this.removeMonitor(Number(id),true);
            }
        }
        if(this.needMonitorIDs["length"]<=0)
            this.stopMonitor();
    }
    private removeMonitor(packetID:number,isTimeOut:boolean=false):void
    {
        let o = this.needMonitorIDs[packetID];
        if(o==null)return;
        for(let i = 0;i<o.ids.length;i++)
        {
            let cids:number[] = this.cancelMonitorIDs[o.ids[i]];
            let index = cids.indexOf(packetID);
            if(index!=-1)
            {
                cids.slice(index,1);
                if(cids.length==0)
                    delete this.cancelMonitorIDs[o.ids[i]];
            }
        }
        if(isTimeOut)
        {
            if(o.callback!=null)
            {
                if(o.callback.length==0)o.callback.apply(o.target);
                else o.callback.call(o.target,packetID);
            }
        }
        this.needMonitorIDs["length"]--;
        delete this.needMonitorIDs[packetID];
    }
    protected onGetReceiveMessage(msg:ClientMessage):void
    {
        if(this.cancelMonitorIDs[msg.action]==undefined)return;
        let cids:number[] = this.cancelMonitorIDs[msg.action];
        for(let i = 0;i<cids.length;i++)
            this.removeMonitor(cids[i]);
    }

    protected onSocketTimeOut():void
    {
        super.onSocketTimeOut();
        this.clearMonitors();
    }
    protected onSocketError():void
    {
        super.onSocketError();
        this.clearMonitors();
    }
    protected onSocketClosed():void
    {
        super.onSocketClosed();
        this.clearMonitors();
    }
    private clearMonitors():void
    {
        if(this.monitorTimer)
        {
            this.monitorTimer.dispose();
            this.monitorTimer = null;
            this.needMonitorIDs = {};
            this.cancelMonitorIDs = {};
        }
    }
}
